package com.qrxl.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qrxl.enums.HjReturnCode;
import com.qrxl.common.exception.CustomException;
import com.qrxl.common.vo.BaseEntity;
import com.qrxl.common.vo.BaseQuery;
import com.qrxl.common.vo.PageVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

/**
 * 分页查询构造器:可获取QueryWrapper、Page、PageVo，如果某字段不想自动生成eq，还可以忽略，然后自定义
 * 默认返回1000条数据
 * 例子：
 * QueryBuilder builder = new QueryBuilder<Equip>().vo2Entity(req, Equip.class)
 * .pageInfo(baseQuery).ignoreFields("sn").addQuery((QueryWrapper queryWrapper) -> {
 * queryWrapper.like("sn", req.getSn());
 * });
 * PageVo<EquipListRes> page = builder.buildPageVO(EquipListRes.class,iEquipService);
 *
 * @author LiuYing
 * @version 1.0
 * @date 20/12/16 下午 11:05
 */
public class QueryBuilder<E extends BaseEntity> {
    private Class<E> entityClass = null;
    private Object queryVO = null;
    private List<String> fieldList = null;
    private QueryPlus queryPlus = null;
    private BaseQuery baseQuery = null;

    /**
     * 查询VO对象
     *
     * @param queryVO
     * @return
     */
    public QueryBuilder vo2Entity(Object queryVO, Class<E> entityClass) {
        this.queryVO = queryVO;
        this.entityClass = entityClass;

        return this;
    }

    /**
     * 忽略生成查询条件字段
     *
     * @param fields
     * @return
     */
    public QueryBuilder ignoreFields(String... fields) {
        if (fields != null) {
            this.fieldList = Arrays.asList(fields);
        }
        return this;
    }

    /**
     * 追加附加查询条件
     *
     * @param queryPlus
     * @return
     */
    public QueryBuilder addQuery(QueryPlus queryPlus) {
        this.queryPlus = queryPlus;
        return this;
    }

    /**
     * 分页信息
     *
     * @param baseQuery
     * @return
     */
    public QueryBuilder pageInfo(BaseQuery baseQuery) {
        this.baseQuery = baseQuery;
        return this;
    }

    public QueryWrapper<E> buildQuery() {
        try {
            E entity = entityClass.getConstructor(null).newInstance();
            // 不为空才构建（为空则构建QueryWrapper<E>供调用者自定义使用）
            if (queryVO != null) {
                BeanUtils.copyProperties(queryVO, entity);
                // 无效字段和忽略字段设置为null，防止生成QueryWrapper信息
                Field[] fields = entityClass.getDeclaredFields();
                for (Field field : fields) {
                    // 是忽略字段
                    if (fieldList != null && fieldList.contains(field.getName())) {
                        field.setAccessible(true);
                        field.set(entity, null);
                        continue;
                    }
                    field.setAccessible(true);
                    Object val = field.get(entity);
                    if (val != null && val instanceof String && StringUtils.isEmpty(val.toString())) {
                        field.set(entity, null);
                    }
                }
            }
            StringUtil.setBankNull(entity);
            QueryWrapper<E> queryWrapper = Wrappers.query(entity);
            if (queryPlus != null) {
                queryPlus.add(queryWrapper);
            }
            addBaseQuery(queryWrapper);
            return queryWrapper;
        } catch (Exception e) {
            throw new CustomException(HjReturnCode.ANY_ERROR, "构建查询失败！");
        }
    }

    /**
     * 构建查询结果
     *
     * @return
     */
    public <S extends IService<E>> Page<E> buildPage(S queryService) {
        if (queryService == null) {
            throw new CustomException(HjReturnCode.ANY_ERROR, "service不能为null！");
        }
        if (baseQuery == null) {
            baseQuery = new BaseQuery();
        }
        if (baseQuery.getPage() == null || baseQuery.getPageSize() == null) {
            baseQuery.setPage(1);
            baseQuery.setPageSize(100000);
        }

        return queryService.page(new Page<E>(baseQuery.getPage(), baseQuery.getPageSize()), buildQuery());
    }

    /**
     * 构建pageVO
     *
     * @param resClass
     * @param queryService
     * @param <S>
     * @param <R>
     * @return
     */
    public <S extends IService<E>, R> PageVo<R> buildPageVO(Class<R> resClass, S queryService) {
        return new PageVo(resClass, buildPage(queryService));
    }

    /**
     * 自定义查询条件
     */
    public interface QueryPlus {
        void add(QueryWrapper queryWrapper) throws ClassNotFoundException;
    }

    /**
     * 追加基础查询
     *
     * @param wrapper
     */
    private void addBaseQuery(QueryWrapper<E> wrapper) {
        if (baseQuery.getId() != null) {
            wrapper.eq("id", baseQuery.getId());
        }
        if (StringUtils.isNoneBlank(baseQuery.getOperator())) {
            wrapper.eq("operator", baseQuery.getOperator());
        }
        if (baseQuery.getStartCreateTime() != null) {
            wrapper.ge("create_time", baseQuery.getStartCreateTime());
        }
        if (baseQuery.getEndCreateTime() != null) {
            wrapper.le("create_time", baseQuery.getEndCreateTime());
        }
        if (baseQuery.getStartUpdateTime() != null) {
            wrapper.gt("update_time", baseQuery.getStartUpdateTime());
        }
        if (baseQuery.getEndUpdateTime() != null) {
            wrapper.lt("update_time", baseQuery.getEndUpdateTime());
        }
        wrapper.orderByDesc("update_time");
    }
}